using System;
using System.Drawing;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
// Todo 
// Bind
// 
namespace SqliteDriver
{
	/// <summary>
	/// Summary description for ConnectionEditForm.
	/// </summary>
	public class SqliteConnectionEditForm : System.Windows.Forms.Form
	{
		private System.Windows.Forms.Button btnClose;
		private IContainer components;
		private System.Windows.Forms.Button btnTest;
		private Panel panel1;
		private TextBox textConn;
		private Label label3;
		private Label label2;
		private Label label1;
		private TextBox textPassword;
		private TextBox textDatabase;
		private TextBox textServer;
		private Label label5;
		private Button btnSave;
		private ListView listConn;
		private ColumnHeader colConnName;
		private ColumnHeader colServer;
		private ColumnHeader colDatabase;
		private ColumnHeader colPassword;
		private Button btnNew;
		private Button btnDelete;
		private Button btnDown;
		private Button btnUp;
		private ContextMenuStrip connPopup;
		//private MenuItem miTest;
		private MenuItem menuItem1;
		private MenuItem menuItem2;
		private ToolStripMenuItem testConnection;
		private ToolStripMenuItem copyConfigToClipboard;
		private Button btnConnect;
		private Button btnBrowse;
		private ToolStripMenuItem connect;
		private ToolStripMenuItem resetDbPassword;
		private ToolStripSeparator toolStripSeparator1;
		private ToolStripMenuItem backupDatabaseFile;
		private ToolStripSeparator toolStripSeparator2;
		private String passwordChangePrevConnection;

		DbViewDriver.IConnectionConfig connectionConfig;
		SqliteDataSource driver;
		ArrayList connections;
		String currentConnectionName = "";
		String filter = "";
		String connectionString = "";

		DbView.ConnectionInfo passwordChangeConnectionInfo;
		bool isQuietPasswordReset = false;

		bool isDirty = false;
		bool isGlobalDirty = false;
		private Label lblFileInfo;

		public SqliteConnectionEditForm(DbViewDriver.IConnectionConfig config, SqliteDataSource driver)
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			this.connectionConfig = config;
			this.driver = driver;
			DbView.ConnectionInfo cic = this.connectionConfig.GetCurrentConnection();
			if (cic != null) this.currentConnectionName = cic.Name;

			// this.m_Connections always holds all of the connections for the driver
			this.connections = new ArrayList();
			List<DbView.ConnectionInfo> connectionList = this.connectionConfig.GetConnections();
			foreach (DbView.ConnectionInfo ci in connectionList)
				this.connections.Add(ci);

			// populate the table.
			int startSel = (this.connections.Count == 0) ? -1 : 0;
			ListViewItem it;
			foreach (DbView.ConnectionInfo ci in this.connections)
			{
				this.ConnInfoToItem(ci, out it);
				listConn.Items.Add(it);
			}
		}

		private bool MatchOne(String source, String part)
		{
			if (part.Length == 0)
				return true;
			return Wildmatch.WildMatch.Match(source, part);
		}

		private bool Matches(DbView.ConnectionInfo ci)
		{
			if (this.filter.Length == 0)
				return true;
			if (MatchOne(ci.Name, this.filter))
				return true;
			if (MatchOne(ci.Server, this.filter))
				return true;
			if (MatchOne(ci.Database, this.filter))
				return true;
			return false;
		}

		private void PopulateList()
		{
			// clear current list
			listConn.Items.Clear();
			ListViewItem it;
			// compare each connection to the filter and display if it matches
			foreach (DbView.ConnectionInfo ci in this.connections)
			{
				if (Matches(ci))
				{
					// create the item
					this.ConnInfoToItem(ci, out it);
					// change text colour when list is filtered
					if (this.filter.Length > 0)
						it.ForeColor = Color.Red;
					// add to list
					listConn.Items.Add(it);
				}
			}
			// set the selection
			ListView.SelectedListViewItemCollection col = this.listConn.SelectedItems;
			if (col.Count == 0 && listConn.Items.Count > 0)
				listConn.Items[0].Selected = true;
		}

		private void ConnectionEditForm2_Shown(object sender, EventArgs e)
		{
			if (this.listConn.Items.Count > 0)
			{
				// set to current connection
				int startSel = 0;
				for (int idx = 0; idx < this.connections.Count; ++idx)
				{
					DbView.ConnectionInfo ci = (DbView.ConnectionInfo)this.connections[idx];
					if (ci.Name == this.currentConnectionName)
					{
						startSel = idx;
						break;
					}
				}
				// normal. highligh 1st connector in list
				this.listConn.Items[startSel].EnsureVisible();
				this.listConn.SelectedIndices.Add(startSel);
				this.listConn.Select();
			}
			else
			{
				// initial set-up. Get straight into adding a new connection
				DbView.ConnectionInfo ci = new DbView.ConnectionInfo();
				AddNew(ci);
			}
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose(bool disposing)
		{
			if (disposing)
			{
				if (components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose(disposing);
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
			System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SqliteConnectionEditForm));
			this.btnClose = new System.Windows.Forms.Button();
			this.btnTest = new System.Windows.Forms.Button();
			this.panel1 = new System.Windows.Forms.Panel();
			this.lblFileInfo = new System.Windows.Forms.Label();
			this.btnBrowse = new System.Windows.Forms.Button();
			this.btnConnect = new System.Windows.Forms.Button();
			this.btnDown = new System.Windows.Forms.Button();
			this.btnUp = new System.Windows.Forms.Button();
			this.btnDelete = new System.Windows.Forms.Button();
			this.btnNew = new System.Windows.Forms.Button();
			this.btnSave = new System.Windows.Forms.Button();
			this.label5 = new System.Windows.Forms.Label();
			this.label3 = new System.Windows.Forms.Label();
			this.label2 = new System.Windows.Forms.Label();
			this.label1 = new System.Windows.Forms.Label();
			this.textPassword = new System.Windows.Forms.TextBox();
			this.textDatabase = new System.Windows.Forms.TextBox();
			this.textServer = new System.Windows.Forms.TextBox();
			this.textConn = new System.Windows.Forms.TextBox();
			this.listConn = new System.Windows.Forms.ListView();
			this.colConnName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
			this.colDatabase = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
			this.colServer = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
			this.colPassword = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
			this.connPopup = new System.Windows.Forms.ContextMenuStrip(this.components);
			this.connect = new System.Windows.Forms.ToolStripMenuItem();
			this.testConnection = new System.Windows.Forms.ToolStripMenuItem();
			this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
			this.backupDatabaseFile = new System.Windows.Forms.ToolStripMenuItem();
			this.resetDbPassword = new System.Windows.Forms.ToolStripMenuItem();
			this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
			this.copyConfigToClipboard = new System.Windows.Forms.ToolStripMenuItem();
			this.menuItem1 = new System.Windows.Forms.MenuItem();
			this.menuItem2 = new System.Windows.Forms.MenuItem();
			this.panel1.SuspendLayout();
			this.connPopup.SuspendLayout();
			this.SuspendLayout();
			// 
			// btnClose
			// 
			this.btnClose.DialogResult = System.Windows.Forms.DialogResult.Cancel;
			this.btnClose.Location = new System.Drawing.Point(605, 62);
			this.btnClose.Name = "btnClose";
			this.btnClose.Size = new System.Drawing.Size(75, 23);
			this.btnClose.TabIndex = 15;
			this.btnClose.Text = "Close";
			this.btnClose.Click += new System.EventHandler(this.BtnClose_Click);
			// 
			// btnTest
			// 
			this.btnTest.Location = new System.Drawing.Point(519, 62);
			this.btnTest.Name = "btnTest";
			this.btnTest.Size = new System.Drawing.Size(75, 23);
			this.btnTest.TabIndex = 14;
			this.btnTest.Text = "&Test";
			this.btnTest.Click += new System.EventHandler(this.BtnTest_Click);
			// 
			// panel1
			// 
			this.panel1.BackColor = System.Drawing.SystemColors.Control;
			this.panel1.Controls.Add(this.lblFileInfo);
			this.panel1.Controls.Add(this.btnBrowse);
			this.panel1.Controls.Add(this.btnConnect);
			this.panel1.Controls.Add(this.btnDown);
			this.panel1.Controls.Add(this.btnUp);
			this.panel1.Controls.Add(this.btnDelete);
			this.panel1.Controls.Add(this.btnNew);
			this.panel1.Controls.Add(this.btnSave);
			this.panel1.Controls.Add(this.label5);
			this.panel1.Controls.Add(this.btnClose);
			this.panel1.Controls.Add(this.btnTest);
			this.panel1.Controls.Add(this.label3);
			this.panel1.Controls.Add(this.label2);
			this.panel1.Controls.Add(this.label1);
			this.panel1.Controls.Add(this.textPassword);
			this.panel1.Controls.Add(this.textDatabase);
			this.panel1.Controls.Add(this.textServer);
			this.panel1.Controls.Add(this.textConn);
			this.panel1.Location = new System.Drawing.Point(0, 271);
			this.panel1.Margin = new System.Windows.Forms.Padding(0);
			this.panel1.Name = "panel1";
			this.panel1.Size = new System.Drawing.Size(683, 119);
			this.panel1.TabIndex = 1;
			// 
			// lblFileInfo
			// 
			this.lblFileInfo.Location = new System.Drawing.Point(385, 66);
			this.lblFileInfo.Name = "lblFileInfo";
			this.lblFileInfo.Size = new System.Drawing.Size(122, 13);
			this.lblFileInfo.TabIndex = 23;
			this.lblFileInfo.Text = "Info: [ n.a. ]";
			this.lblFileInfo.TextAlign = System.Drawing.ContentAlignment.TopRight;
			// 
			// btnBrowse
			// 
			this.btnBrowse.Location = new System.Drawing.Point(304, 61);
			this.btnBrowse.Name = "btnBrowse";
			this.btnBrowse.Size = new System.Drawing.Size(75, 23);
			this.btnBrowse.TabIndex = 19;
			this.btnBrowse.Text = "&Browse ...";
			this.btnBrowse.Click += new System.EventHandler(this.BtnBrowse_Click);
			// 
			// btnConnect
			// 
			this.btnConnect.Location = new System.Drawing.Point(605, 89);
			this.btnConnect.Name = "btnConnect";
			this.btnConnect.Size = new System.Drawing.Size(75, 23);
			this.btnConnect.TabIndex = 18;
			this.btnConnect.Text = "&Connect";
			this.btnConnect.Click += new System.EventHandler(this.BtnConnect_Click);
			// 
			// btnDown
			// 
			this.btnDown.Location = new System.Drawing.Point(605, 35);
			this.btnDown.Name = "btnDown";
			this.btnDown.Size = new System.Drawing.Size(75, 23);
			this.btnDown.TabIndex = 17;
			this.btnDown.Text = "Move Do&wn";
			this.btnDown.Click += new System.EventHandler(this.BtnDown_Click);
			// 
			// btnUp
			// 
			this.btnUp.Location = new System.Drawing.Point(605, 10);
			this.btnUp.Name = "btnUp";
			this.btnUp.Size = new System.Drawing.Size(75, 23);
			this.btnUp.TabIndex = 16;
			this.btnUp.Text = "Move &Up";
			this.btnUp.Click += new System.EventHandler(this.BtnUp_Click);
			// 
			// btnDelete
			// 
			this.btnDelete.Location = new System.Drawing.Point(519, 35);
			this.btnDelete.Name = "btnDelete";
			this.btnDelete.Size = new System.Drawing.Size(75, 23);
			this.btnDelete.TabIndex = 11;
			this.btnDelete.Text = "&Delete";
			this.btnDelete.Click += new System.EventHandler(this.BtnDelete_Click);
			// 
			// btnNew
			// 
			this.btnNew.Location = new System.Drawing.Point(519, 10);
			this.btnNew.Name = "btnNew";
			this.btnNew.Size = new System.Drawing.Size(75, 23);
			this.btnNew.TabIndex = 12;
			this.btnNew.Text = "&New";
			this.btnNew.Click += new System.EventHandler(this.BtnNew_Click);
			// 
			// btnSave
			// 
			this.btnSave.Location = new System.Drawing.Point(519, 90);
			this.btnSave.Name = "btnSave";
			this.btnSave.Size = new System.Drawing.Size(75, 23);
			this.btnSave.TabIndex = 10;
			this.btnSave.Text = "&Save";
			this.btnSave.Click += new System.EventHandler(this.BtnSave_Click);
			// 
			// label5
			// 
			this.label5.AutoSize = true;
			this.label5.Location = new System.Drawing.Point(5, 94);
			this.label5.Name = "label5";
			this.label5.Size = new System.Drawing.Size(53, 13);
			this.label5.TabIndex = 8;
			this.label5.Text = "Password";
			// 
			// label3
			// 
			this.label3.AutoSize = true;
			this.label3.Location = new System.Drawing.Point(5, 66);
			this.label3.Name = "label3";
			this.label3.Size = new System.Drawing.Size(72, 13);
			this.label3.TabIndex = 4;
			this.label3.Text = "Database File";
			// 
			// label2
			// 
			this.label2.AutoSize = true;
			this.label2.Location = new System.Drawing.Point(5, 40);
			this.label2.Name = "label2";
			this.label2.Size = new System.Drawing.Size(36, 13);
			this.label2.TabIndex = 2;
			this.label2.Text = "Folder";
			// 
			// label1
			// 
			this.label1.AutoSize = true;
			this.label1.Location = new System.Drawing.Point(5, 13);
			this.label1.Name = "label1";
			this.label1.Size = new System.Drawing.Size(92, 13);
			this.label1.TabIndex = 0;
			this.label1.Text = "Connection Name";
			// 
			// textPassword
			// 
			this.textPassword.Enabled = false;
			this.textPassword.Location = new System.Drawing.Point(103, 91);
			this.textPassword.Name = "textPassword";
			this.textPassword.Size = new System.Drawing.Size(195, 20);
			this.textPassword.TabIndex = 9;
			// 
			// textDatabase
			// 
			this.textDatabase.Location = new System.Drawing.Point(103, 63);
			this.textDatabase.Name = "textDatabase";
			this.textDatabase.Size = new System.Drawing.Size(195, 20);
			this.textDatabase.TabIndex = 5;
			// 
			// textServer
			// 
			this.textServer.Location = new System.Drawing.Point(103, 37);
			this.textServer.Name = "textServer";
			this.textServer.Size = new System.Drawing.Size(404, 20);
			this.textServer.TabIndex = 3;
			// 
			// textConn
			// 
			this.textConn.Location = new System.Drawing.Point(103, 10);
			this.textConn.Name = "textConn";
			this.textConn.Size = new System.Drawing.Size(404, 20);
			this.textConn.TabIndex = 1;
			this.textConn.TextChanged += new System.EventHandler(this.ConnInfo_TextChanged);
			// 
			// listConn
			// 
			this.listConn.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
            this.colConnName,
            this.colDatabase,
            this.colServer,
            this.colPassword});
			this.listConn.ContextMenuStrip = this.connPopup;
			this.listConn.FullRowSelect = true;
			this.listConn.GridLines = true;
			this.listConn.HideSelection = false;
			this.listConn.Location = new System.Drawing.Point(0, -1);
			this.listConn.MultiSelect = false;
			this.listConn.Name = "listConn";
			this.listConn.Size = new System.Drawing.Size(683, 271);
			this.listConn.TabIndex = 0;
			this.listConn.UseCompatibleStateImageBehavior = false;
			this.listConn.View = System.Windows.Forms.View.Details;
			this.listConn.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.ListConn_OnColumnClick);
			this.listConn.SelectedIndexChanged += new System.EventHandler(this.ListView2_SelectedIndexChanged);
			this.listConn.DoubleClick += new System.EventHandler(this.ListConn_DoubleClick);
			this.listConn.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.ListConn_KeyPress);
			this.listConn.MouseUp += new System.Windows.Forms.MouseEventHandler(this.ListConn_MouseUp);
			// 
			// colConnName
			// 
			this.colConnName.Text = "Connection Name";
			this.colConnName.Width = 200;
			// 
			// colDatabase
			// 
			this.colDatabase.Text = "Database File";
			this.colDatabase.Width = 112;
			// 
			// colServer
			// 
			this.colServer.Text = "Folder";
			this.colServer.Width = 277;
			// 
			// colPassword
			// 
			this.colPassword.Text = "Password";
			this.colPassword.Width = 84;
			// 
			// connPopup
			// 
			this.connPopup.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.connect,
            this.testConnection,
            this.toolStripSeparator1,
            this.backupDatabaseFile,
            this.resetDbPassword,
            this.toolStripSeparator2,
            this.copyConfigToClipboard});
			this.connPopup.Name = "connPopup";
			this.connPopup.Size = new System.Drawing.Size(256, 126);
			// 
			// connect
			// 
			this.connect.Name = "connect";
			this.connect.Size = new System.Drawing.Size(255, 22);
			this.connect.Text = "Connect";
			this.connect.Click += new System.EventHandler(this.Connect_Click);
			// 
			// testConnection
			// 
			this.testConnection.Name = "testConnection";
			this.testConnection.Size = new System.Drawing.Size(255, 22);
			this.testConnection.Text = "Test connection";
			this.testConnection.Click += new System.EventHandler(this.BtnTest_Click);
			// 
			// toolStripSeparator1
			// 
			this.toolStripSeparator1.Name = "toolStripSeparator1";
			this.toolStripSeparator1.Size = new System.Drawing.Size(252, 6);
			// 
			// backupDatabaseFile
			// 
			this.backupDatabaseFile.Name = "backupDatabaseFile";
			this.backupDatabaseFile.Size = new System.Drawing.Size(255, 22);
			this.backupDatabaseFile.Text = "Backup Database file";
			this.backupDatabaseFile.Click += new System.EventHandler(this.Backup_Click);
			// 
			// resetDbPassword
			// 
			this.resetDbPassword.Name = "resetDbPassword";
			this.resetDbPassword.Size = new System.Drawing.Size(255, 22);
			this.resetDbPassword.Text = "Reset Password";
			this.resetDbPassword.Click += new System.EventHandler(this.ResetPassword_Click);
			// 
			// toolStripSeparator2
			// 
			this.toolStripSeparator2.Name = "toolStripSeparator2";
			this.toolStripSeparator2.Size = new System.Drawing.Size(252, 6);
			// 
			// copyConfigToClipboard
			// 
			this.copyConfigToClipboard.Name = "copyConfigToClipboard";
			this.copyConfigToClipboard.Size = new System.Drawing.Size(255, 22);
			this.copyConfigToClipboard.Text = "Copy to clipboard as Config string";
			this.copyConfigToClipboard.Click += new System.EventHandler(this.CopyConfig_Click);
			// 
			// menuItem1
			// 
			this.menuItem1.Index = -1;
			this.menuItem1.Text = "Copy as ADO";
			// 
			// menuItem2
			// 
			this.menuItem2.Index = -1;
			this.menuItem2.Text = "Copy as Config";
			// 
			// SqliteConnectionEditForm
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(685, 389);
			this.Controls.Add(this.listConn);
			this.Controls.Add(this.panel1);
			this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
			this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
			this.Name = "SqliteConnectionEditForm";
			this.ShowInTaskbar = false;
			this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
			this.Text = "Database Connection";
			this.Shown += new System.EventHandler(this.ConnectionEditForm2_Shown);
			this.panel1.ResumeLayout(false);
			this.panel1.PerformLayout();
			this.connPopup.ResumeLayout(false);
			this.ResumeLayout(false);

		}
		#endregion

		///////////////////////////////////////////////////////////////////////////////////////
		// helpers
		//
		class MaxDb
		{
			internal const int SQLCE_DEFAULTSIZEMB = 256;

			internal MaxDb(String memo)
			{
				this.ParseMemo(memo);
			}
			
			internal MaxDb(String sizeMb, bool isEnabled)
			{
				this.SizeMb = sizeMb;
				this.Enabled = isEnabled;
			}
			
			internal String SizeMb {get; set; }
			internal bool Enabled {get; set; }

			internal bool IsValid()
			{
				int sizeMb;
				if (!int.TryParse(this.SizeMb, out sizeMb)) return false;
				return (sizeMb > 0); // non-negative, nomn-zero values only
			}
			
			private void ParseMemo(string memo)
			{
				this.SizeMb = "";		// means not
				this.Enabled = false;	// only relevant when size set
				if (memo.Length > 0)
				{
					// ought only to try this on overidden values
					int pos = memo.IndexOf("MAXDB");
					if (pos != -1)
					{
						pos += (5 + 1); // skip the token plus the =
						this.SizeMb = memo.Substring(pos);
					}
					this.Enabled = (memo[0] != '-');  // only disabled if prefixed with -
				}
			}

			public override string ToString()
			{
				if (this.SizeMb.Length == 0) return "";
				return (!this.Enabled) ? "-" : "" + String.Format("MAXDB={0}", this.SizeMb);
			}
		}

		// hookey maxdb size helper(s)
		// stored in UID property of connection info in the form MAXDB=9999
		// in the dialog it may be prefixed with - to indicate that the value was set then the 
		// checkbox was unchecked to disable it. In this case we leave the value in case they want it again
		
		//private string MaxdbMemo(DbView.ConnectionInfo ci)
		//{
		//    if (ci == null) return ""; // no data so can't know
		//    return ci.UID;
		//}

		//bool IsMaxDbOverride(DbView.ConnectionInfo ci)
		//{
		//    String s = MaxdbMemo(ci);
		//    if (s.Length == 0) return false;
		//    if (s[0] == '-') return false;
		//    if (s.IndexOf("MAXDB") == 0) return true;
		//    return false;
		//}
		
		//long MaxDbSize(DbView.ConnectionInfo ci)
		//{
		//    long sqlceDefault = 256L * 1000L * 1000L;
		//    String s = MaxdbMemo(ci);

		//    if (s.Length == 0) return sqlceDefault;
		//    // ought only to try this on overidden values
		//    int iPos = s.IndexOf("MAXDB");
		//    if (iPos == -1) return sqlceDefault;
		//    iPos += (5 + 1); // skip the token plus the =
		//    String sizeStr = s.Substring(iPos);
		//    int sizeMb;
		//    if (!int.TryParse(sizeStr,out sizeMb)) return -1; // error state
		//    return (long)sizeMb * 1000L * 1000L;
		//}

		//long MaxDbSizeOverride(DbView.ConnectionInfo ci, bool valid)
		//{
		//    String s = MaxdbMemo(ci);
		////}

		private void SelectedToControls()
		{
			ListView.SelectedListViewItemCollection col = this.listConn.SelectedItems;
			if (col.Count >= 1)
			{
				ListViewItem li = col[0]; // assume only 1 selected
				textConn.Text = li.SubItems[0].Text;
				textDatabase.Text = li.SubItems[1].Text;
				textServer.Text = li.SubItems[2].Text;
				textPassword.Text = li.SubItems[3].Text;
				// Size (held encoded in the ci.UID property)
				ControlsFromSizeMemo(li.Tag);
				this.isDirty = false;  // controls in synch with list

				FileInfo(Path.Combine(textServer.Text, textDatabase.Text));
			}
		}

		private int UsedPC(string databaseFile, long maxSize)
		{
			if (File.Exists(databaseFile))
			{
				long bytes = new FileInfo(databaseFile).Length;
				long usedPC = (bytes * 100) / maxSize;
				return (int)usedPC;
			}
			return -1;
		}

		private void FileInfo(string databaseFile)
		{
			// allow for the case where 
			String fileInfo = "Size: ";
			lblFileInfo.ForeColor = label1.ForeColor;
			if (File.Exists(databaseFile))
			{
				long bytes = new FileInfo(databaseFile).Length;
				decimal lengthMb = ((decimal)bytes)/1000000;
				fileInfo += lengthMb.ToString("#,##0.000")+"MB";
			}
			else
			{
				fileInfo += "n.a.";
			}
			lblFileInfo.Text = fileInfo;
		}

		//private long EffectiveMax(DbView.ConnectionInfo ci, out bool isValid)
		//{
		//    isValid = true;
		//    long defaultSize = 256 * 1000 * 1000; // sqlce default size 256 mb possible 256 * 1024 * 1024. lets play safe
		//    if (ci == null) return defaultSize;
		//    if (ci.UID.Length == 0) return defaultSize;
		//    if (ci.UID[0] != '+') return defaultSize;
		//    int sizeMb;
		//    isValid = int.TryParse(ci.UID.Substring(1), out sizeMb);
		//    if (!isValid) return defaultSize;
		//    return (long)sizeMb * 1000L * 1000L;
		////}

		private long EffectiveMax(DbView.ConnectionInfo ci)
		{
			long megabyteConverter = 1000L * 1000L;
			long defaultSize = (long)MaxDb.SQLCE_DEFAULTSIZEMB * megabyteConverter;

			MaxDb decoder = new MaxDb(ci.UID);
			if (decoder.Enabled == false) return defaultSize;
			if (decoder.IsValid() == false) return defaultSize;
			long sizeMb = Convert.ToInt32(decoder.SizeMb);
			return sizeMb * megabyteConverter;
		}

		//private String SizeFromControls()
		//{
		//    MaxDb encoder = new MaxDb(sizeStr, active);
		//    return encoder.ToString();
		//}

		private void ControlsFromSizeMemo(object memo)
		{
			bool checkState = false;
			String sizeStr = "";
			if (memo != null)
			{
				DbView.ConnectionInfo ci = (DbView.ConnectionInfo)memo;
				if (memo != null)
				{
					MaxDb decoder = new MaxDb(ci.UID);
					sizeStr = decoder.SizeMb;
					checkState = decoder.Enabled;
				}
			}
			//textMaxDbSize.Text = sizeStr;
			//checkSize.Checked = checkState;
			//labelMb.Enabled = checkState;
			//textMaxDbSize.Enabled = checkState;
		}

		private void ControlsToSelected()
		{
			ListView.SelectedListViewItemCollection col = this.listConn.SelectedItems;
			if (col.Count >= 1)
			{
				ListViewItem li = col[0]; // assume only 1 selected
				li.SubItems[0].Text = textConn.Text;
				li.SubItems[1].Text = textDatabase.Text;
				li.SubItems[2].Text = textServer.Text;
				li.SubItems[3].Text = textPassword.Text;
				// also update the linked object
				DbView.ConnectionInfo ci = (DbView.ConnectionInfo)li.Tag;
				ci.Name = li.SubItems[0].Text;
				ci.Database = li.SubItems[1].Text;
				ci.Server = li.SubItems[2].Text;
				ci.PWD = li.SubItems[3].Text;
				// set the UID
				ci.UID = "";
				this.isGlobalDirty = true; // assume this means a change is made
				this.isDirty = false; // controls in synch with list
			}
		}

		//private void itemToConnInfo(ListViewItem li, out DbView.ConnectionInfo ci)
		//{
		//    ci = new DbView.ConnectionInfo();
		//    ci.Name = li.SubItems[0].Text;
		//    ci.Database = li.SubItems[1].Text;
		//    ci.Server = li.SubItems[2].Text;
		//    ci.PWD = li.SubItems[3].Text;
		//    DbView.ConnectionInfo prevCi = li.Tag as DbView.ConnectionInfo;
		//    if (prevCi != null)
		//        ci.UID = prevCi.UID;
		////}

		private void ConnInfoToItem(DbView.ConnectionInfo ci, out ListViewItem li)
		{
			String[] rowData = new String[5];
			rowData[0] = ci.Name;
			rowData[1] = ci.Database;
			rowData[2] = ci.Server;
			rowData[3] = ci.PWD;
			li = new ListViewItem(rowData);
			li.Tag = ci;
		}

		private void AddNew(DbView.ConnectionInfo ci)
		{
			String createMessage = @"
If you wish to create a new database file press [Yes].
If you wish to associate this connection with an existing
database file press [No].

Create a new database file for the new connection?
";
			DialogResult res = MessageBox.Show(createMessage, "New connection", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
			if (res == DialogResult.Cancel) return;
			if (res == DialogResult.Yes)
			{
				SaveFileDialog createFileDialog = new SaveFileDialog();

				createFileDialog.FileName = "";
				createFileDialog.Filter = "SQLite database files (*.db*;*.sqlite*)|*.db*;*.sqlite*|All files (*.*)|*.*";
				createFileDialog.RestoreDirectory = true;

				if (createFileDialog.ShowDialog() == DialogResult.OK)
				{
					// break it up
					this.textServer.Text = Path.GetDirectoryName(createFileDialog.FileName);
					this.textDatabase.Text = Path.GetFileName(createFileDialog.FileName);
					// 
					ci.Name = Path.GetFileNameWithoutExtension(createFileDialog.FileName);
					ci.Server = textServer.Text;
					ci.Database = textDatabase.Text;
					string connectionString = SqliteDataSource.MakeConnectionString(ci);
					// this.driver.CreateDatabaseFile(connectionString);
					// do this so that if the user enters a password it is reset.
					ResetPassword(ci, true); // reset with quiet mode.
				}
				else 
					return;
			}

			// add to store
			// add to front
			this.connections.Insert(0, ci);
			ListViewItem li;
			this.ConnInfoToItem(ci, out li);
			this.listConn.Items.Insert(0, li);
			this.listConn.SelectedItems.Clear();
			this.listConn.SelectedIndices.Add(0);
			this.textConn.Focus();
			this.isGlobalDirty = true;
		}

		private void SetMatchString(String newMatchIn)
		{
			String newMatch = newMatchIn.ToLower();
			if (newMatch.CompareTo(this.filter) == 0)
				return; // do nothing if nothing to do.
			this.filter = newMatch;
			PopulateList();
		}

		private bool ValidatesOk()
		{
			// check whether the dirty flag is set.
			if (!this.isGlobalDirty) return true; // try this
			String driverName = this.driver.DriverName;
			// 
			int seq = 0;
			List<DbView.ConnectionInfo> connectionList = new List<DbView.ConnectionInfo>();
			foreach (DbView.ConnectionInfo ci in this.connections)
			{
				if (!IsEmpty(ci)) // ignore empties
				{
					if (!SqliteDataSource.IsValid(ci))
					{
						String msg = String.Format("Incomplete Row: [{0}] - please complete or remove it", seq + 1);
						MessageBox.Show(this, msg, "Entry Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
						return false;
					}
					ci.Driver = driverName; // fix up with drive description
					connectionList.Add(ci);
				}
				++seq;
			}
			this.connectionConfig.Save(connectionList);
			return true; // OK
		}

		private bool IsEmpty(DbView.ConnectionInfo ci)
		{
			if (ci.Name.Length > 0) return false;
			if (ci.Server.Length > 0) return false;
			if (ci.Database.Length > 0) return false;
			// don't bother with the other ones just abandon them
			return true; // for now
		}

		//private bool OldValidatesOk()
		//{
		//    // new Style
		//    int iSeq = 0;
		//    DbView.ConnectionInfo[] aci = new DbView.ConnectionInfo[this.m_Connections.Count];
		//    foreach (DbView.ConnectionInfo ci in this.m_Connections)
		//    {
		//        if (!SqlCeDataSource.IsValid(ci))
		//        {
		//            String msg = String.Format("Incomplete Row: [{0}] - please complete or remove it", iSeq + 1);
		//            MessageBox.Show(this, msg, "Entry Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
		//            return false;
		//        }
		//        aci[iSeq++] = ci;
		//    }
		//    // check whether the dirty flag is set.
		//    if (this.m_bGlobalDirty)
		//    {
		//        String driverName = m_Driver.GetDriverName();
		//        // good to save
		//        List<DbView.ConnectionInfo> ConnectionList = new List<DbView.ConnectionInfo>();
		//        foreach (DbView.ConnectionInfo ci in aci)
		//        {
		//            ci.Driver = driverName; // fix up with drive description
		//            ConnectionList.Add(ci);
		//        }
		//        m_Config.Save(ConnectionList);
		//    }
		//    return true;
		////}

		private bool OnClose()
		{
			if (this.isDirty)
			{
				DialogResult res = MessageBox.Show("Save current edit", "Unsaved changes", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
				if (res == DialogResult.Cancel)
					return false;
				if (res == DialogResult.Yes)
					this.ControlsToSelected();
			}
			return ValidatesOk();
		}

		private void BtnClose_Click(object sender, System.EventArgs e)
		{
			if (OnClose())
				this.Close();
		}

		private void BtnTest_Click(object sender, System.EventArgs e)
		{
			DbView.ConnectionInfo ci = new DbView.ConnectionInfo();
			ci.Name = textConn.Text;
			ci.Server = textServer.Text;
			ci.Database = textDatabase.Text;
			ci.PWD = textPassword.Text;
			//MaxDb encoder = new MaxDb(textMaxDbSize.Text, checkSize.Checked);
			//if (encoder.Enabled)
			//    ci.UID = encoder.ToString();

			// make a connection
			String connstr = SqliteDataSource.MakeConnectionString(ci);
			// try select @@version 
			String message;
			// new Helper(this.GetAccessor()).TestConnection(connstr, out message);
			String caption = String.Format("{0}.{1}", ci.Server, ci.Database);
			Helper.TestConnection(connstr, out message);
			//message = "OK";
			MessageBoxIcon ico = (message == "OK") ? MessageBoxIcon.Information :
													 MessageBoxIcon.Warning;
			MessageBox.Show(this, message, caption, MessageBoxButtons.OK, ico);
			// catch and report errors
			// save if the test passes
			if (message == "OK" && this.isDirty)
				this.ControlsToSelected();
		}

		private void ListView2_SelectedIndexChanged(object sender, EventArgs e)
		{
			this.SelectedToControls();
		}

		private void BtnSave_Click(object sender, EventArgs e)
		{
			this.ControlsToSelected();
			
			if (this.passwordChangeConnectionInfo == ConnInfofromSelection())
			{
			    String message;
			    MessageBoxIcon msgIcon = MessageBoxIcon.Information;
			    try
			    {
			        bool reset = Helper.ResetPassword(this.passwordChangePrevConnection, this.passwordChangeConnectionInfo.PWD);
			        message = String.Format("Password reset on {0} OK", this.passwordChangeConnectionInfo.Database);
					this.textPassword.Enabled = false;

			    }
			    catch (Exception exc)
			    {
			        message = String.Format("Password reset on {0} failed. Message was\n{1}", this.passwordChangeConnectionInfo.Database, exc.Message);
			        msgIcon = MessageBoxIcon.Error;
			    }
			    if (!this.isQuietPasswordReset)
			        MessageBox.Show(message, "Password Reset", MessageBoxButtons.OK, msgIcon);
			}
		}

		private void BtnNew_Click(object sender, EventArgs e)
		{
			DbView.ConnectionInfo ci = new DbView.ConnectionInfo();
			AddNew(ci);
		}

		private void BtnDelete_Click(object sender, EventArgs e)
		{
			ListView.SelectedListViewItemCollection col = this.listConn.SelectedItems;
			if (col.Count >= 1)
			{
				int idx = this.listConn.SelectedIndices[0];
				ListViewItem li = col[0]; // assume only 1 selected
				// remove from internal array
				DbView.ConnectionInfo ci = (DbView.ConnectionInfo)li.Tag;
				if (ci.Name == this.currentConnectionName)
					MessageBox.Show(this, "Please do not delete the current connection", "Deletion denied", MessageBoxButtons.OK, MessageBoxIcon.Warning);
				else
				{
					ci.Delete();
					this.connections.Remove(ci);
					this.isGlobalDirty = true;
					// remove from list view
					this.listConn.Items.Remove(li);
					while (idx >= this.listConn.Items.Count)
						--idx;
					if (idx >= 0)
						this.listConn.SelectedIndices.Add(idx);
				}
			}
		}

		//private void CheckSize_CheckedChanged(object sender, EventArgs e)
		//{
		//    UpdateSizeUI();
		//}

		private void ListConn_DoubleClick(object sender, EventArgs e)
		{
			BtnConnect_Click(sender, e);
		}

		private void BtnUp_Click(object sender, EventArgs e)
		{
			// must move the display and the underlying object
			// find target item to move
			ListView.SelectedListViewItemCollection col = this.listConn.SelectedItems;
			if (col.Count >= 1)
			{
				// only the first
				int idx = this.listConn.SelectedIndices[0];
				if (idx > 0)
				{
					ListViewItem li = this.listConn.Items[idx - 1]; // get item just above
					DbView.ConnectionInfo ci1 = (DbView.ConnectionInfo)li.Tag;              // get associated connection object of placemarker
					li = col[0];                            // assume only 1 selected
					this.listConn.Items.Remove(li);         // remove the item
					this.listConn.Items.Insert(idx - 1, li);  // insert it in the correct place
					DbView.ConnectionInfo ci2 = (DbView.ConnectionInfo)li.Tag;        // get associated object of moved item
					// now move in array
					int pos = this.connections.LastIndexOf(ci1);  // find marker
					this.connections.Remove(ci2);         // remove object from old pos
					this.connections.Insert(pos, ci2);    // reinsert
					this.isGlobalDirty = true;
				}
			}
		}

		private void BtnDown_Click(object sender, EventArgs e)
		{
			ListView.SelectedListViewItemCollection col = this.listConn.SelectedItems;
			if (col.Count >= 1)
			{
				int idx = this.listConn.SelectedIndices[0];
				if (idx + 1 < this.listConn.Items.Count)
				{
					ListViewItem li = this.listConn.Items[idx + 1]; // get item just below
					DbView.ConnectionInfo ci1 = (DbView.ConnectionInfo)li.Tag;              // get associated connection object
					li = col[0];                        // assume only 1 selected
					this.listConn.Items.Remove(li);
					this.listConn.Items.Insert(idx + 1, li);
					DbView.ConnectionInfo ci2 = (DbView.ConnectionInfo)li.Tag;              // get associated item
					// now move in array
					int pos = this.connections.LastIndexOf(ci1);
					this.connections.Remove(ci2);       // remove from old pos
					this.connections.Insert(pos, ci2);  // reinsert
					this.isGlobalDirty = true;
				}
			}
		}

		private void ListConn_KeyPress(object sender, KeyPressEventArgs e)
		{
			char c = e.KeyChar;
			if ((c >= '0' && c <= '9')
				|| (c >= 'A' && c <= 'Z')
				|| (c >= 'a' && c <= 'z'))
			{
				SetMatchString(this.filter + c);
				e.Handled = true;
			}
			else if (c == 8)
			{
				int l = this.filter.Length;
				if (l > 0)
				{
					SetMatchString(this.filter.Substring(0, l - 1));
					e.Handled = true;
				}
			}
			else if (c == 27)
			{
				SetMatchString("");
				e.Handled = true;
			}
			else if (c == 13)
			{
				this.BtnConnect_Click(sender, e);
				e.Handled = true;
			}
		}

		private void ListConn_MouseUp(object sender, MouseEventArgs e)
		{
			if (e.Button == MouseButtons.Right)
			{
			}
		}

		private DbView.ConnectionInfo ConnInfofromSelection()
		{
			ListView.SelectedListViewItemCollection col = this.listConn.SelectedItems;
			if (col.Count >= 1)
			{
				ListViewItem li = col[0]; // assume only 1 selected
				return (DbView.ConnectionInfo)li.Tag;
			}
			return null;
		}

		private void CopyConfig_Click(object sender, EventArgs e)
		{
			DbView.ConnectionInfo ci = ConnInfofromSelection();
			if (ci != null)
			{
				String connStr = SqliteDataSource.MakeConnectionString(ci);
				String clipText = String.Format("String connStr = @\"{0}\";", connStr);
				Clipboard.SetText(clipText);
			}
		}

		private void BtnConnect_Click(object sender, EventArgs e)
		{
			if (OnClose())
			{
				ConnectAndClose();
			}
		}

		private void ConnectAndClose()
		{
			DbView.ConnectionInfo ci = ConnInfofromSelection();
			if (ci != null)
			{
				this.connectionString = ci.Name;
				// connect
				this.connectionConfig.SetCurrentConnection(ci);
				DialogResult = DialogResult.OK; // use OK to signal closing with connection request
			}
			this.Close();
		}

		private void Connect_Click(object sender, EventArgs e)
		{
			ConnectAndClose();
		}

		private void ConnInfo_TextChanged(object sender, EventArgs e)
		{
			this.isDirty = true;
		}

		// hacked from Web: 
		private void ListConn_OnColumnClick(object sender, System.Windows.Forms.ColumnClickEventArgs e)
		{
			// sorter is not attached until the first sort click
			bool isSorterAttached = (listConn.ListViewItemSorter != null);
			if (!isSorterAttached)
				listConn.ListViewItemSorter = new ListViewSorter();
			// defensive programming statement 
			if (!(listConn.ListViewItemSorter is ListViewSorter)) return;
			// get the attached sorter
			ListViewSorter sorter = (ListViewSorter)listConn.ListViewItemSorter;

			// logic for ascending/descending sort
			// if same column and not the first time in
			if (sorter.LastSort == e.Column && isSorterAttached)
			{
				// toggle order based on state
				if (listConn.Sorting == SortOrder.Ascending)
					listConn.Sorting = SortOrder.Descending;
				else
					listConn.Sorting = SortOrder.Ascending;
			}
			else
			{
				// fall back to ascending sort
				listConn.Sorting = SortOrder.Ascending;
			}
			// set the column to sort by
			sorter.ByColumn = e.Column;
			// do it?
			listConn.Sort();
		}

		private void BtnBrowse_Click(object sender, EventArgs e)
		{
			// find a .mdf file.
			// set the name in the connection box
			OpenFileDialog openFileDialog1 = new OpenFileDialog();

			openFileDialog1.InitialDirectory = this.textServer.Text;
			openFileDialog1.FileName = this.textDatabase.Text;
			openFileDialog1.Filter = "SQLite database files (*.db*;*.sqlite*)|*.db*;*.sqlite*|All files (*.*)|*.*";
			openFileDialog1.RestoreDirectory = true;

			if (openFileDialog1.ShowDialog() == DialogResult.OK)
			{
				// break it up
				this.textServer.Text = Path.GetDirectoryName(openFileDialog1.FileName);
				this.textDatabase.Text = Path.GetFileName(openFileDialog1.FileName);
			}
		}

		private void ResetPassword_Click(object sender, EventArgs e)
		{
			DbView.ConnectionInfo ci = ConnInfofromSelection();
			ResetPassword(ci, false);
		}

		private void ResetPassword(DbView.ConnectionInfo ci, bool quiet)
		{
			this.passwordChangeConnectionInfo = ci;
			this.isQuietPasswordReset = quiet;
			this.passwordChangePrevConnection = SqliteDataSource.MakeConnectionString(ci);
			this.textPassword.Enabled = true;
			this.textPassword.Focus();
		}

		private void Backup_Click(object sender, EventArgs e)
		{
			DbView.ConnectionInfo ci = ConnInfofromSelection();
			BackupFile(ci);
		}

		private void BackupFile(DbView.ConnectionInfo ci)
		{
			String sourceFileName = Path.Combine(ci.Server, ci.Database);
			String name = Path.GetFileNameWithoutExtension(ci.Database);
			String ext = Path.GetExtension(ci.Database);
			String extra = MakeDateTimePart();
			String backupFileName = Path.Combine(ci.Server, String.Format("{0}_{1}{2}", name, extra, ext));
			try
			{
				File.Copy(sourceFileName, backupFileName);
				MessageBox.Show(String.Format("{0} copied to:\n{1}", sourceFileName, backupFileName), "Backup complete", 
								MessageBoxButtons.OK, MessageBoxIcon.Information);
			}
			catch (Exception exc)
			{
				MessageBox.Show(String.Format("Error copying\n{0} to:\n{1}\n\n{2}", sourceFileName, backupFileName, exc.Message), 
								"Error during backup", 	MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		private String MakeDateTimePart()
		{
			System.DateTime now = new DateTime();
			now = DateTime.Now;
			return now.ToString("yyyyMMdd_hhmmss");
		}

	}

	// hacked from Web: 
	public class ListViewSorter : System.Collections.IComparer
	{
		public int Compare(object o1, object o2)
		{
			if (!(o1 is ListViewItem))
				return (0);
			if (!(o2 is ListViewItem))
				return (0);

			ListViewItem lvi1 = (ListViewItem)o2;
			string str1 = lvi1.SubItems[ByColumn].Text;
			ListViewItem lvi2 = (ListViewItem)o1;
			string str2 = lvi2.SubItems[ByColumn].Text;

			int result;
			if (lvi1.ListView.Sorting == SortOrder.Ascending)
				result = String.Compare(str2, str1);
			else
				result = String.Compare(str1, str2);

			LastSort = ByColumn;

			return (result);
		}

		public int ByColumn
		{
			get { return column; }
			set { column = value; }
		}
		int column = 0;

		public int LastSort
		{
			get { return lastColumn; }
			set { lastColumn = value; }
		}
		int lastColumn = 0;
	}
}
